#include "../include/utf8.h"
#include <stdio.h>
#include <stdlib.h>

#define UNICODE_HAN_SIZE 206000
#define UNICODE_HAN_CODE_POINT_MIN 0X3400
#define UNICODE_SC_SIZE 21000
#define UNICODE_SC_CODE_POINT_MIN 0X4E00
#define UNICODE_SC_CODE_POINT_MAX 0X9FA5
#define TRUE 1
#define FALSE 0

uint8_t is_skipable_word(uint32_t code_point)
{
    if (code_point < UNICODE_SC_CODE_POINT_MIN // 非中文字符
        || code_point == 65281                 // ！
        || code_point == 65292                 // ，
        || code_point == 65306                 // ：
        || code_point == 65307                 // ；
        || code_point == 65311                 // ？
    )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

void build_dic(uint32_t ts_mapping[], uint32_t dic[], const char *words)
{
    int charIdx = 0;
    int error_char_idx = 0;

    Utf8CodePoint info = {.codePoint = -1, .size = -1};
    while (words[charIdx] != '\0')
    {
        error_char_idx = charIdx;
        if (-1 == utf8CodePoint(&words[charIdx], &info))
        {
            exit(1);
        }
        charIdx += info.size;

        if (is_skipable_word(info.codePoint) == TRUE)
        {
            continue;
        }

        if (info.codePoint > UNICODE_SC_CODE_POINT_MAX || info.codePoint < UNICODE_SC_CODE_POINT_MIN)
        {
            printf("Unexpected code point : %d in %s of %s\n", info.codePoint, &words[error_char_idx], words);
            continue;
        }

        int index = info.codePoint - UNICODE_SC_CODE_POINT_MIN;
        uint32_t s_code_point = ts_mapping[info.codePoint];
        if (s_code_point == 0)
        {
            dic[index] = info.codePoint;
        }
        else
        {
            dic[index] = s_code_point;
        }
    };
}

void save_to_file(uint32_t dic[], char *path)
{
    Utf8CharInfo info = {.point = {'\0', '\0', '\0', '\0'}, .size = -1};
    char buff[6];
    int buffIdx = 0;

    FILE *fp = fopen(path, "w");
    for (int i = 0; i < UNICODE_SC_SIZE; i++)
    {
        if (0 == dic[i])
        {
            continue;
        }

        buffIdx = 0;

        if (-1 == utf8Char(dic[i], &info))
        {
            exit(1);
        }
        for (int j = 0; j < info.size; j++)
        {
            buff[buffIdx++] = info.point[j];
        }

        buff[buffIdx++] = '\n';
        buff[buffIdx] = '\0';

        fputs(buff, fp);
    }
    fclose(fp);
}

void setup_ts_mapping(uint32_t mapping[], char *path)
{
    char buff[128];
    int pointIdx = 0;
    int charIdx = 0;
    Utf8CodePoint info = {.codePoint = -1, .size = -1};

    FILE *fp = fopen(path, "r");
    while (fgets(buff, 1024, fp) != NULL)
    {
        charIdx = 0;

        if (-1 == utf8CodePoint(&buff[charIdx], &info))
        {
            exit(1);
        }
        uint32_t t_code_point = info.codePoint;
        charIdx += info.size;

        if (t_code_point >= UNICODE_HAN_SIZE)
        {
            printf("Unexpected traditional code point : %d\n", t_code_point);
        }

        if (-1 == utf8CodePoint(&buff[charIdx], &info))
        {
            exit(1);
        }
        mapping[t_code_point] = info.codePoint;
    }
    fclose(fp);
}